#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define EXECUCOES 40
#define NUM_GERACOES 100
#define SIZE_MATERIAL 34
#define SIZE_POP 100
#define TCROSS 100
#define TOUR 1
#define TMUT 45

#define ESTOCASTICO 1
#define ELITISMO 1

//#define CLASSE_PROCURADA 1

#define IGUAL 0
#define DIFERENTE 1
#define MAIOR_IGUAL 2
#define MENOR 3
#define NUM_OPERADORES 4

#define AUSENTE 0
#define MAX_PRESENCA 4

int seed;
//int classe_procurada = 1;
//int training = 1;

typedef struct atributo{
    //int presente;
    int peso;
    int operador;
    int valor;
}ATRIB, *P_ATRIB, **DP_ATRIB;

typedef struct indi{
    ATRIB atributos[SIZE_MATERIAL];
    int false_positive;
    int false_negative;
    int true_positive;
    int true_negative;
    //int sendmory[SIZE_MATERIAL];
    float evaluate;
}INDI, *P_INDI, **DP_INDI;

INDI create_individuo_aleatorio();
INDI create_individuo_aleatorio_metodo_comum();
INDI create_individuo_com_material(ATRIB *atributos);
//INDI create_individuo_com_material(int *sendmory);

P_INDI copiar_individuo(P_INDI inicial);
//P_INDI create_individuo_aleatorio_ponteiro();

DP_INDI create_population();
DP_INDI copy_population(DP_INDI pop);

int compara_igualdade_individuos(P_INDI indi1, P_INDI indi2);
int compara_avaliacao_individuos_const_void(const void *indi1, const void *indi2);
int compara_avaliacao_individuos_inverso_const_void(const void *indi1, const void *indi2);
//int populacao_contem_individuo(DP_INDI population, P_INDI indiv, int index);

//int *crossover_ciclico(P_INDI indi1, P_INDI indi2);
ATRIB *crossover_dois_pontos(P_INDI indi1, P_INDI indi2);

void mutacao_local_troca(DP_INDI pop);
void imprime_individuo(P_INDI pointer);
void imprime_individuo_fast(P_INDI pointer);
void avaliar_individuo(P_INDI pointer);
void torneio(DP_INDI pop, DP_INDI pais);
void copy_population_to_other(DP_INDI p1, DP_INDI p2, int number);

void executa_algoritmo_genetico(DP_INDI populacao, void(*seleciona_pais)(DP_INDI pop, DP_INDI pais), ATRIB *(*crossover)(P_INDI indi1, P_INDI indi2),
                                int (*compara_individuos)(const void* indi1, const void* indi2), void (*avaliador)(P_INDI indi), void (*mutacao)(DP_INDI indi));

